package com.ruicar.afs.cloud.account.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.account.common.entity.*;
import com.ruicar.afs.cloud.account.common.mapper.*;
import com.ruicar.afs.cloud.account.common.service.VoucherEntryService;
import com.ruicar.afs.cloud.account.vo.VoucherEntryVo;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author infinity
 * @version 1.0
 * @date 2020/6/18 14:55
 */
@Service
@AllArgsConstructor
public class VoucherEntryServiceImpl extends ServiceImpl<VoucherEntryMapper, VoucherEntry> implements VoucherEntryService {
    private final UidGenerator uidGenerator;
    private final VoucherRuleItemMapper voucherRuleItemMapper;
    private final VoucherRuleExpressMapper voucherRuleExpressMapper;
    private final VoucherRuleExpressAtomMapper voucherRuleExpressAtomMapper;
    private final VoucherRuleInputMappingMapper voucherRuleInputMappingMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public VoucherEntryVo checkAndSave(VoucherEntryVo voucherEntryVo) {
        this.check(voucherEntryVo);
        VoucherEntry voucherEntry = VoucherEntry.convertFromVo(voucherEntryVo);
        this.save(voucherEntry);
        voucherEntryVo.setId(voucherEntry.getId());
        return voucherEntryVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public VoucherEntry checkAndUpdate(VoucherEntryVo voucherEntryVo) {
        this.check(voucherEntryVo);
        VoucherEntry dbVoucherEntry = this.baseMapper.selectById(Long.valueOf(voucherEntryVo.getId()));
        VoucherEntry voucherEntry = VoucherEntry.convertFromVo(voucherEntryVo);
        BeanUtil.copyProperties(voucherEntry, dbVoucherEntry, "chineseLang","programLang","amountExpression","createBy", "createTime", "id", "deleteToken");
        this.updateById(dbVoucherEntry);
        return dbVoucherEntry;
    }

    @Override
    public List<VoucherEntryVo> list(Long correlationId) {
        return this.list(Wrappers.<VoucherEntry>query().lambda().eq(VoucherEntry::getCorrelationId, correlationId).orderByAsc(VoucherEntry::getOrderNum))
                .stream().map(voucherEntry -> {
                    VoucherEntryVo voucherEntryVo = new VoucherEntryVo();
                    voucherEntryVo.setId(voucherEntry.getId());
                    voucherEntryVo.setLendingDirection(voucherEntry.getLendingDirection());
                    voucherEntryVo.setSubjectCode(voucherEntry.getSubjectCode());
                    voucherEntryVo.setSubjectName(voucherEntry.getSubjectName());
                    voucherEntryVo.setOrderNum(voucherEntry.getOrderNum());
                    voucherEntryVo.setExplanation(voucherEntry.getExplanation());
                    voucherEntryVo.setCorrelationId(voucherEntry.getCorrelationId());
                    voucherEntryVo.setRuleNo(voucherEntry.getRuleNo());
                    voucherEntryVo.setChineseLang(voucherEntry.getChineseLang());
                    voucherEntryVo.setProgramLang(voucherEntry.getProgramLang());
                    if (StringUtils.isNotBlank(voucherEntry.getAuxiliaryAccountingItems())) {
                        String str[] = voucherEntry.getAuxiliaryAccountingItems().split(",");
                        voucherEntryVo.setItemsList(Arrays.asList(str));
                    }
                    return voucherEntryVo;
                }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        this.update(Wrappers.<VoucherEntry>lambdaUpdate().eq(VoucherEntry::getId, id)
                .set(VoucherEntry::getDeleteToken, uidGenerator.getUID())
                //逻辑删除 1 为删除
                .set(VoucherEntry::getDelFlag, '1'));
        this.delRule(id);
        return true;
    }

    private void check(VoucherEntryVo voucherEntryVo) {
        long count = this.baseMapper.selectCount(Wrappers.<VoucherEntry>lambdaQuery()
                .eq(VoucherEntry::getCorrelationId, voucherEntryVo.getCorrelationId()).eq(VoucherEntry::getOrderNum, voucherEntryVo.getOrderNum()).ne(voucherEntryVo.getId() != null, VoucherEntry::getId, voucherEntryVo.getId()));
        Assert.isTrue(count < 1, "凭证分录序号[" + voucherEntryVo.getOrderNum() + "]重复");
    }

    private void delRule(Long id) {
        //删除VoucherRuleItem 信息
        voucherRuleItemMapper.delete(Wrappers.<VoucherRuleItem>lambdaQuery().eq(VoucherRuleItem::getRuleId, id));
        //删除值映射
        voucherRuleInputMappingMapper.delete(Wrappers.<VoucherRuleInputMapping>lambdaQuery().eq(VoucherRuleInputMapping::getRuleId, id));
        //删除VoucherRuleExpress 信息
        voucherRuleExpressMapper.delete(Wrappers.<VoucherRuleExpress>lambdaQuery().eq(VoucherRuleExpress::getRuleId, id));
        //删除VoucherRuleExpressAtom 信息
        voucherRuleExpressAtomMapper.delete(Wrappers.<VoucherRuleExpressAtom>lambdaQuery().eq(VoucherRuleExpressAtom::getRuleId, id));
    }
}
